package top.lgd.service.study;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.NumberUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.IService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import top.lgd.base.LgdConstants;
import top.lgd.mapper.study.CatalogMapper;
import top.lgd.pojo.entity.study.Catalog;
import top.lgd.pojo.entity.study.Content;
import top.lgd.pojo.res.TreeRes;
import top.lgd.pojo.res.study.CatalogRes;
import top.lgd.service.LgdCacheService;
import top.lgd.utils.TreeUtils;

import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 学习目录表 服务实现类
 *
 * @author YYJ
 * @version 1.0
 * @since 2023/12/15 10:10
 */
@Service
public class CatalogService extends ServiceImpl<CatalogMapper, Catalog> implements IService<Catalog> {

    @Autowired
    protected LgdCacheService lgdCacheService;
    @Autowired
    protected ContentService contentService;

    /**
     * 【有缓存】
     *
     * @param catalogId
     * @return
     */
    public Catalog queryCatalog(Long catalogId) {
        Catalog catalog = null;
        if (null != catalogId && 0 != catalogId) {
            String key = LgdConstants.KEY_STUDY_CATALOG_INFO + catalogId;
            catalog = lgdCacheService.get(key);
            if (null != catalog) {
                return catalog;
            }

            catalog = getById(catalogId);
            if (null != catalog) {
                lgdCacheService.put(key, catalog);
            }
        }
        return catalog;
    }

    /**
     * 查询完整目录名称
     *
     * @param catalogId
     * @return
     */
    public String queryAllName(Long catalogId) {
        StringBuilder sb = new StringBuilder();
        Catalog catalog = queryCatalog(catalogId);
        if (null != catalog) {
            String[] ancestors = catalog.getAncestors().split(LgdConstants.ANCESTORS_SPLIT);
            for (String ancestor : ancestors) {
                Long id = NumberUtil.parseLong(ancestor);
                Catalog tmp = queryCatalog(id);
                sb.append(null != tmp ? tmp.getName() + LgdConstants.ANCESTORS_SPLIT : "");
            }
            sb.append(catalog.getName());
        }
        return sb.toString();
    }

    /**
     * 查询所有子目录
     *
     * @param catalogId
     * @return
     */
    public Set<Long> queryDescendantIds(Long catalogId) {
        Set<Long> idSets = new HashSet<>();
        String key = LgdConstants.KEY_STUDY_CATALOG_OWNER + catalogId;

        Catalog catalog = queryCatalog(catalogId);
        if (null != catalog) {
            idSets = lgdCacheService.get(key);
            if (CollectionUtil.isNotEmpty(idSets)) {
                return idSets;
            }

            QueryWrapper<Catalog> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq(LgdConstants.COLUMN_ID, catalogId)
                    .or().likeRight(LgdConstants.COLUMN_ANCESTORS, catalog.getAncestors() + catalogId + LgdConstants.ANCESTORS_SPLIT);
            List<Catalog> catalogList = list(queryWrapper);
            if (CollectionUtil.isNotEmpty(catalogList)) {
                idSets = catalogList.stream().map(Catalog::getId).collect(Collectors.toSet());
            }
            idSets.add(catalogId);
            lgdCacheService.put(key, idSets);
        }
        return idSets;
    }

    /**
     * 查询目录树
     *
     * @param userId
     * @return
     */
    public List<TreeRes> genCatalogTree(Long userId) {
        QueryWrapper<Catalog> queryWrapper = new QueryWrapper();
        queryWrapper.eq(LgdConstants.COLUMN_DATA_USER_ID, userId)
                .orderByAsc(LgdConstants.COLUMN_PARENT_ID, LgdConstants.COLUMN_SORT_NUM);
        List<Catalog> catalogList = list(queryWrapper);

        List<TreeRes> treeResList = BeanUtil.copyToList(catalogList, TreeRes.class);
        if (CollectionUtil.isNotEmpty(treeResList)) {
            treeResList.forEach(m -> {
                m.setKey(m.getId());
                m.setTitle(m.getName());
            });
        }
        Map<Long, List<TreeRes>> parentMap = treeResList.stream().collect(Collectors.groupingBy(TreeRes::getParentid));
        return TreeUtils.genTree(parentMap.get(LgdConstants.LONG_ZERO), parentMap);
    }

    /**
     * 查询目录树列表
     *
     * @param userId
     * @return
     */
    public List<CatalogRes> genTreeList(Long userId) {
        QueryWrapper<Catalog> queryWrapper = new QueryWrapper();
        queryWrapper.eq(LgdConstants.COLUMN_DATA_USER_ID, userId)
                .orderByAsc(LgdConstants.COLUMN_PARENT_ID, LgdConstants.COLUMN_SORT_NUM);
        List<Catalog> catalogList = list(queryWrapper);

        List<CatalogRes> catalogResList = BeanUtil.copyToList(catalogList, CatalogRes.class);
        Map<Long, List<CatalogRes>> parentMap = catalogResList.stream().collect(Collectors.groupingBy(CatalogRes::getParentid));
        return getTree(parentMap.get(LgdConstants.LONG_ZERO), parentMap);
    }

    /**
     * 【清缓存】
     *
     * @param catalog
     * @param userId
     * @return
     */
    public boolean saveOrUpdate(Catalog catalog, Long userId) {
        if (null != catalog.getId()) {
            clearCache(catalog.getId());
            UpdateWrapper<Catalog> updateWrapper = new UpdateWrapper();
            updateWrapper.eq(LgdConstants.COLUMN_ID, catalog.getId())
                    .eq(LgdConstants.COLUMN_DATA_USER_ID, userId);
            return update(catalog, updateWrapper);
        } else {
            catalog.setDataUserId(userId);
            return save(catalog);
        }
    }

    /**
     * 【清缓存】
     *
     * @param id
     * @param userId
     * @return
     */
    public boolean remove(Long id, Long userId) {
        if (0 == count(new QueryWrapper<Catalog>().eq(LgdConstants.COLUMN_PARENT_ID, id))
                && 0 == contentService.count(new QueryWrapper<Content>().eq(LgdConstants.COLUMN_CATALOG_ID, id))) {
            clearCache(id);
            return remove(new QueryWrapper<Catalog>()
                    .eq(LgdConstants.COLUMN_ID, id)
                    .eq(LgdConstants.COLUMN_DATA_USER_ID, userId));
        }
        return false;
    }

    private void clearCache(Long catalogId) {
        lgdCacheService.delete(LgdConstants.KEY_STUDY_CATALOG_INFO + catalogId);
        lgdCacheService.delete(LgdConstants.KEY_STUDY_CATALOG_OWNER + catalogId);
    }

    private List<CatalogRes> getTree(List<CatalogRes> catalogResList, Map<Long, List<CatalogRes>> parentMap) {
        if (CollectionUtil.isNotEmpty(catalogResList)) {
            catalogResList.forEach(p -> {
                List<CatalogRes> childrenList = parentMap.get(p.getId());
                if (CollectionUtil.isNotEmpty(childrenList)) {
                    childrenList.stream().peek(c -> c.setChildren(parentMap.get(c.getId()))).collect(Collectors.toList());
                    p.setChildren(childrenList.stream().filter(c -> p.getId().equals(c.getParentid())).collect(Collectors.toList()));
                }
            });
        }
        return catalogResList;
    }
}